﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description: WebDeployApplicationViewModel
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using VmroleAuthor.Commands;
using VmroleAuthor.Models;

namespace VmroleAuthor.ViewModels
{
    public class WebDeployApplicationViewModel : TreeViewItemViewModel, IAddScriptCommand, IDataErrorInfo, IProduceValidationResults, IRemoveChildItem, ICanBeRemovedFromTree
    {       
        private readonly VmRoleResourceExtensionViewModel vmRoleResourceExtensionViewModel;
        private readonly WebDeployApplication webDeployApplication;    
        private readonly ObservableCollection<WebDeployParameterViewModel> webDeployParameterViewModels;
      
        private StringParameterizableProperty packagePassword;

        private ReferencedApplicationPayloadViewModel webDeployPackage;

        public static class PropertyNames
        {
            public const string Summary = "Summary";
            public const string DeploymentName = "DeploymentName";        
            public const string PackagePassword = "PackagePassword";
            public const string WebDeployPackage = "WebDeployPackage";
            public const string WebDeployParameterViewModels = "WebDeployParameterViewModels";
        }  

        public WebDeployApplicationViewModel(
            WebDeployApplication webDeployApplication,
            ApplicationProfileViewModel applicationProfileViewModel,
            VmRoleResourceExtensionViewModel resourceExtensionViewModel)
            : base(applicationProfileViewModel, true)
        {
            if (webDeployApplication == null)
            {
                webDeployApplication = new WebDeployApplication();
            }
            this.webDeployApplication = webDeployApplication;
            this.vmRoleResourceExtensionViewModel = resourceExtensionViewModel;
            this.webDeployParameterViewModels = new ObservableCollection<WebDeployParameterViewModel>();         

            if (this.webDeployApplication.WebDeploymentParameters != null)
            {
                foreach (WebDeploymentParameters webDeployParameters in this.webDeployApplication.WebDeploymentParameters)
                {
                    this.webDeployParameterViewModels.Add(new WebDeployParameterViewModel(webDeployParameters, this.vmRoleResourceExtensionViewModel));
                }
            }        
            this.GetWebDeployParametersForSelectedPackage();

            this.AddWebDeployParameterCommand = new RelayCommand(
             param => this.AddWebDeployParameter(),
             param => this.CanAddWebDeployParameter());

            this.DeleteWebDeployParameterCommand = new RelayCommand(
                param => this.DeleteWebDeployParameter((WebDeployParameterViewModel)param),
                param => this.CanDeleteWebDeployParameter((WebDeployParameterViewModel)param));   
            
            this.ValidationResults = new ObservableCollection<CloudServiceModelValidationResult>();                
        }

        public WebDeployApplication WebDeployApplication
        {
            get { return this.webDeployApplication; }
        }

        public string Summary
        {
            get
            {
               if (string.IsNullOrEmpty(this.webDeployApplication.DeploymentName))
               {
                   return "Web Application";
               }
               return "Web Application (" + this.webDeployApplication.DeploymentName + ")";
            }
        }     

        public ReferencedApplicationPayloadViewModel WebDeployPackage
        {
            get
            {
                if (this.webDeployPackage == null)
                {
                    Func<string> getter = () => this.webDeployApplication.ApplicationPayloadId;                
                    Action<string> setter = delegate(string value) { this.webDeployApplication.ApplicationPayloadId = value; };
                    this.webDeployPackage = new ReferencedApplicationPayloadViewModel(this.vmRoleResourceExtensionViewModel, ValidationHelper.PayloadType.WebDeployPackage, getter, setter, true, PropertyNames.WebDeployPackage);
                }
                return this.webDeployPackage;
            }
        }

        public  string DeploymentName
        {
            get { return this.webDeployApplication.DeploymentName; }
            set 
            { 
                this.webDeployApplication.DeploymentName = value;
                this.OnPropertyChanged(PropertyNames.DeploymentName);
                this.OnPropertyChanged(PropertyNames.Summary);
            }
        }      

        public List<string> AvailableParameters
        {
            get { return this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel.AvailableParameters; }
        }

        public StringParameterizableProperty PackagePassword
        {
            get
            {
                //lazy init
                if (this.packagePassword == null)
                {
                    Func<string> paramValueGetter = () => this.webDeployApplication.PackagePassword;                   
                    Action<string> paramValueSetter = delegate(string value) { this.webDeployApplication.PackagePassword = value; };
                    Func<string> autoParamNameGetter = () => (this.webDeployApplication.DeploymentName ?? string.Empty) + PropertyNames.PackagePassword;
                    ViewDefParamInfo viewDefParamInfo = new ViewDefParamInfo
                    {
                        ViewDefParameterType = ViewDefParameterType.SecureString,
                        DefaultEnglishLabelText = "Web deploy package password"
                    };

                    this.packagePassword = new StringParameterizableProperty(
                        PropertyNames.PackagePassword,
                        paramValueGetter,
                        paramValueSetter,
                        autoParamNameGetter,
                        ParameterType.SecureString,
                        "Web deploy package password",
                         this.vmRoleResourceExtensionViewModel.ResourceExtensionParametersViewModel,
                         false,
                         viewDefParamInfo
                        );
                }
                return this.packagePassword;
            }
        }     

        public ObservableCollection<WebDeployParameterViewModel>  WebDeployParameterViewModels
        {
            get
            {
                return this.webDeployParameterViewModels;
            }
        }


        private void GetWebDeployParametersForSelectedPackage()
        {                     
            // Reconcile the generated with currently declared parameters when the package is open for edit              
        }            

        public ICommand AddWebDeployParameterCommand
        {
            get;
            private set;
        }

        public ICommand DeleteWebDeployParameterCommand
        {
            get;
            private set;
        }

        public bool CanAddWebDeployParameter()
        {
            return true;
        }

        public void AddWebDeployParameter()
        {
            WebDeploymentParameters webDeploymentParameters = new WebDeploymentParameters();
            var webDeployParameterViewModel = new WebDeployParameterViewModel(webDeploymentParameters, this.vmRoleResourceExtensionViewModel);
            this.webDeployParameterViewModels.Add(webDeployParameterViewModel);
            if (this.webDeployApplication.WebDeploymentParameters == null)
            {
                this.webDeployApplication.WebDeploymentParameters = new List<WebDeploymentParameters>();
            }
            this.webDeployApplication.WebDeploymentParameters.Add(webDeployParameterViewModel.WebDeploymentParameters);
        }

        public bool CanDeleteWebDeployParameter(WebDeployParameterViewModel webDeployParameterViewModel)
        {
            return true;
        }

        public void DeleteWebDeployParameter(WebDeployParameterViewModel webDeployParameterViewModel)
        {
            if (webDeployParameterViewModel != null)
            {
                webDeployParameterViewModel.Cleanup();
                if (this.webDeployApplication.WebDeploymentParameters != null)
                {
                    this.webDeployApplication.WebDeploymentParameters.Remove(webDeployParameterViewModel.WebDeploymentParameters);
                }
                this.webDeployParameterViewModels.Remove(webDeployParameterViewModel);                 
            }                      
        }

        protected override void LoadChildren()
        {
            if (this.webDeployApplication.ScriptCommands != null)
            {
                foreach (ProvisioningScript provisioningScript in this.webDeployApplication.ScriptCommands)
                {                    
                    this.Children.Add(new ProvisioningScriptViewModel(provisioningScript, this, this.vmRoleResourceExtensionViewModel));
                }
            }                         
        }

        public void RemoveChild(TreeViewItemViewModel childItem)
        {            
            var provisioningScriptViewModel = childItem as ProvisioningScriptViewModel;
            if (provisioningScriptViewModel != null)
            {
                provisioningScriptViewModel.Cleanup();
                this.webDeployApplication.ScriptCommands.Remove(provisioningScriptViewModel.ProvisioningScript);
                this.Children.Remove(childItem);
            }
        }

        public bool CanAddScriptCommand
        {
            get { return true; }
        }

        public void AddScriptCommand()
        {
            this.IsExpanded = true;
            if (this.webDeployApplication.ScriptCommands == null)
            {
                this.webDeployApplication.ScriptCommands = new List<ProvisioningScript>();                
            }
           
            ProvisioningScript scriptCommand = new ProvisioningScript();
            scriptCommand.ExecutableAndParams = new ExecutableAndParams();            
            this.webDeployApplication.ScriptCommands.Add(scriptCommand);
            var scriptCommandViewModel = new ProvisioningScriptViewModel(scriptCommand, this, this.vmRoleResourceExtensionViewModel);
            this.Children.Add(scriptCommandViewModel);           
            scriptCommandViewModel.IsSelected = true;
        }

        

        public string this[string propertyName]
        {
            get
            {
                string error = null;
                switch (propertyName)
                {
                    case PropertyNames.DeploymentName:
                        error = ValidationHelper.ValidateNotNullOrEmpty(this.webDeployApplication.DeploymentName) ??
                                ValidationHelper.ValidateApplicationDeploymentNamesAreUnique(this.vmRoleResourceExtensionViewModel.ResourceExtensionDefinition);
                        break;                  
                }                             
                return error;
            }           
        }

        public string Error { get; set; }

        public ObservableCollection<CloudServiceModelValidationResult> ValidationResults { get; private set; }

        public void UpdateValidationResults()
        {
            this.IsExpanded = true;
            ModelValidationResultsHelper.UpdateValidationResults(this, typeof(PropertyNames));
            //Add any other cross-field validations error            
        }

        public void Cleanup()
        {
            this.IsExpanded = true;
            ParametersAndPayloadCleanupHelper.CleanupParametersAndPayload(this, typeof(PropertyNames));        
        }
    }
}


